package p2pcdnsim.cdn;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import p2pcdnsim.exception.ClientInWrongComunityException;
import p2pcdnsim.network.ApplicationLayer;
import p2pcdnsim.network.ClientNode;
import p2pcdnsim.network.GenericAddress;
import p2pcdnsim.network.NetworkLayer;
import p2pcdnsim.network.RouterNode;
import p2pcdnsim.network.TransportLayer;

import desmoj.core.simulator.Model;


public class ClientComunity{
	private Model model;
	RouterNode node;
	private List<Long> clients;
	private int ID_GEN;
	private CDN cdn;
	private Map<String,ClientNode> clientNodes;

	public ClientComunity(CDN cdn, RouterNode node) {
		this.model = cdn.getModel();
		clients = new ArrayList<Long>();
		ID_GEN = 1;
		this.cdn = cdn;
		this.node = node;
		this.clientNodes = new Hashtable<String, ClientNode>();
	}
	

	public void addClient(long clientID) {
		clients.add(clientID);
	}

	public synchronized void startNewClient(long clientID, int objectID) throws ClientInWrongComunityException {
		if(!clients.contains(clientID)) throw new ClientInWrongComunityException();
		
		//Create the client node
		ClientNode clientNode = new ClientNode(clientID);
		//Build network stack
		clientNode.setNetworkLayer(new NetworkLayer(model));
		clientNode.getNetworkLayer().setTransportLayer(new TransportLayer(model));
		clientNode.getNetworkLayer().getTransportLayer().setApplicationLayer(new ApplicationLayer(model));	
		//Attribute client node address
		clientNode.getNetworkLayer().setNetworkAddress(new GenericAddress((GenericAddress)node.getNetworkLayer().getDefaultAddress(),""+(ID_GEN++)));
		//add node on router LAN bus
		node.getLinkBus().addClientNode(clientNode);
		clientNode.setLinkBus(node.getLinkBus());
		
		//Create the client
		VoDClient client = new VoDClient(this.model,"Client","VodClient:"+clientNode.getNetworkLayer().getDefaultAddress(),this);
		client.setDNSAddress(cdn.getRequestRedirectorAddress());
		client.setRequestObject(objectID);
		clientNode.getNetworkLayer().getTransportLayer().getApplicationLayer().setApplicationProcess(client);
		
		//keep track of nodes created
		clientNodes.put(client.getClientId(), clientNode);
		System.out.println("["+cdn.currentTime()+"] Client "+clientID+" created with node client address "+clientNode.getNetworkLayer().getDefaultAddress());
	}


	int getNumberOfClient() {
		return clients.size();
	}


	public void disposeClient(Client client) {
		ClientNode clientNode = clientNodes.remove(client.getClientId());
		//System.out.println(client.getClientId()+": "+clientNode);
		node.getLinkBus().removeClientNode(clientNode);
	}
	
}
